import 'dart:async';
import 'package:test/test.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart' as sqflite;
import '../entities/product.dart';
import 'product_dao.dart';

void main() {
  late sqflite.Database database;
  late ProductDao productDao;
  late StreamController<String> changeListener;

  setUpAll(() async {
    // 初始化sqflite_ffi用于测试
    sqflite.sqfliteFfiInit();
    sqflite.databaseFactory = sqflite.databaseFactoryFfi;
  });

  setUp(() async {
    // 创建内存数据库用于测试
    database = await sqflite.openDatabase(
      ':memory:',
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE products (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            description TEXT NOT NULL,
            price REAL NOT NULL,
            category_id INTEGER NOT NULL,
            is_active INTEGER NOT NULL DEFAULT 1,
            tags TEXT,
            created_at TEXT
          )
        ''');
      },
    );

    changeListener = StreamController<String>.broadcast();
    productDao = ProductDao(database, changeListener);
  });

  tearDown(() async {
    await changeListener.close();
    await database.close();
  });

  group('ProductDao 基础操作测试', () {
    test('insert - 插入单个产品', () async {
      final product = Product(
        name: 'Laptop',
        description: 'High-performance laptop for gaming',
        price: 1299.99,
        categoryId: 1,
        isActive: true,
        tags: '["electronics", "gaming", "computer"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      expect(id, greaterThan(0));
    });

    test('inserts - 批量插入产品', () async {
      final products = [
        Product(
          name: 'Smartphone',
          description: 'Latest Android smartphone',
          price: 699.99,
          categoryId: 1,
          isActive: true,
          tags: '["electronics", "mobile", "android"]',
          createdAt: DateTime.now(),
        ),
        Product(
          name: 'Headphones',
          description: 'Wireless noise-cancelling headphones',
          price: 299.99,
          categoryId: 2,
          isActive: true,
          tags: '["audio", "wireless", "accessories"]',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await productDao.inserts(products);
      expect(ids.length, equals(2));
      expect(ids.every((id) => id > 0), isTrue);
    });

    test('findById - 根据ID查找产品', () async {
      final product = Product(
        name: 'Tablet',
        description: 'Lightweight tablet for reading and browsing',
        price: 399.99,
        categoryId: 1,
        isActive: true,
        tags: '["electronics", "tablet", "portable"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      final foundProduct = await productDao.findById(id);

      expect(foundProduct, isNotNull);
      expect(foundProduct!.name, equals('Tablet'));
      expect(foundProduct.price, equals(399.99));
      expect(foundProduct.categoryId, equals(1));
      expect(foundProduct.isActive, isTrue);
    });

    test('findById - 查找不存在的产品', () async {
      final foundProduct = await productDao.findById(999);
      expect(foundProduct, isNull);
    });

    test('exists - 检查产品是否存在', () async {
      final product = Product(
        name: 'Monitor',
        description: '4K gaming monitor',
        price: 549.99,
        categoryId: 1,
        isActive: true,
        tags: '["electronics", "monitor", "gaming"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      final exists = await productDao.exists(id);
      final notExists = await productDao.exists(999);

      expect(exists, isTrue);
      expect(notExists, isFalse);
    });

    test('update - 更新产品', () async {
      final product = Product(
        name: 'Keyboard',
        description: 'Mechanical gaming keyboard',
        price: 149.99,
        categoryId: 2,
        isActive: true,
        tags: '["peripherals", "gaming", "keyboard"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      final updatedProduct = product.copyWith(
        id: id,
        price: 129.99,
        isActive: false,
        description: 'Mechanical gaming keyboard - SALE',
      );

      await productDao.update(updatedProduct);
      final foundProduct = await productDao.findById(id);

      expect(foundProduct!.price, equals(129.99));
      expect(foundProduct.isActive, isFalse);
      expect(foundProduct.description,
          equals('Mechanical gaming keyboard - SALE'));
    });

    test('delete - 删除产品', () async {
      final product = Product(
        name: 'Mouse',
        description: 'Wireless gaming mouse',
        price: 79.99,
        categoryId: 2,
        isActive: true,
        tags: '["peripherals", "gaming", "mouse"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      final productWithId = product.copyWith(id: id);

      final deletedRows = await productDao.delete(productWithId);
      expect(deletedRows, equals(1));

      final foundProduct = await productDao.findById(id);
      expect(foundProduct, isNull);
    });

    test('deleteById - 根据ID删除产品', () async {
      final product = Product(
        name: 'Speaker',
        description: 'Bluetooth portable speaker',
        price: 89.99,
        categoryId: 2,
        isActive: true,
        tags: '["audio", "bluetooth", "portable"]',
        createdAt: DateTime.now(),
      );

      final id = await productDao.insert(product);
      await productDao.deleteById(id);

      final foundProduct = await productDao.findById(id);
      expect(foundProduct, isNull);
    });

    test('findAll - 查找所有产品', () async {
      final products = [
        Product(
          name: 'Webcam',
          description: 'HD webcam for video calls',
          price: 59.99,
          categoryId: 2,
          isActive: true,
          tags: '["accessories", "video", "webcam"]',
          createdAt: DateTime.now(),
        ),
        Product(
          name: 'Router',
          description: 'WiFi 6 wireless router',
          price: 199.99,
          categoryId: 3,
          isActive: true,
          tags: '["networking", "wifi", "router"]',
          createdAt: DateTime.now(),
        ),
      ];

      await productDao.inserts(products);
      final allProducts = await productDao.findAll();

      expect(allProducts.length, greaterThanOrEqualTo(2));
      expect(allProducts.any((p) => p.name == 'Webcam'), isTrue);
      expect(allProducts.any((p) => p.name == 'Router'), isTrue);
    });

    test('updates - 批量更新产品', () async {
      final products = [
        Product(
          name: 'SSD',
          description: '1TB NVMe SSD',
          price: 129.99,
          categoryId: 1,
          isActive: true,
          tags: '["storage", "ssd", "nvme"]',
          createdAt: DateTime.now(),
        ),
        Product(
          name: 'RAM',
          description: '16GB DDR4 RAM',
          price: 79.99,
          categoryId: 1,
          isActive: true,
          tags: '["memory", "ram", "ddr4"]',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await productDao.inserts(products);
      final updatedProducts = [
        products[0].copyWith(id: ids[0], price: 119.99),
        products[1].copyWith(id: ids[1], isActive: false),
      ];

      await productDao.updates(updatedProducts);

      final foundProduct1 = await productDao.findById(ids[0]);
      final foundProduct2 = await productDao.findById(ids[1]);

      expect(foundProduct1!.price, equals(119.99));
      expect(foundProduct2!.isActive, isFalse);
    });

    test('deletes - 批量删除产品', () async {
      final products = [
        Product(
          name: 'CPU',
          description: 'Intel Core i7 processor',
          price: 329.99,
          categoryId: 1,
          isActive: true,
          tags: '["processor", "intel", "cpu"]',
          createdAt: DateTime.now(),
        ),
        Product(
          name: 'GPU',
          description: 'NVIDIA RTX 4070 graphics card',
          price: 599.99,
          categoryId: 1,
          isActive: true,
          tags: '["graphics", "nvidia", "gpu"]',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await productDao.inserts(products);
      final productsWithIds = [
        products[0].copyWith(id: ids[0]),
        products[1].copyWith(id: ids[1]),
      ];

      final deletedRows = await productDao.deletes(productsWithIds);
      expect(deletedRows, equals(2));

      final foundProduct1 = await productDao.findById(ids[0]);
      final foundProduct2 = await productDao.findById(ids[1]);

      expect(foundProduct1, isNull);
      expect(foundProduct2, isNull);
    });
  });
}
